package com.kzx.blog.service.impl;

import com.kzx.blog.config.model.Constant;
import com.kzx.blog.config.model.FailedException;
import com.kzx.blog.config.model.FailedInfo;
import com.kzx.blog.mapper.TokenMapper;
import com.kzx.blog.mapper.UserMapper;
import com.kzx.blog.model.Token;
import com.kzx.blog.model.User;
import com.kzx.blog.service.IUser;
import com.kzx.blog.service.model.UserLoginParam;
import com.kzx.blog.service.model.UserSO;
import com.kzx.blog.util.DateUtils;
import com.kzx.blog.util.MD5Utils;
import com.kzx.blog.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author kongz
 * @version 1.0 2021/11/25 16:43
 * @description 用户业务实现类
 */
@Service
public class UserImpl implements IUser {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TokenMapper tokenMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public UserSO login(UserLoginParam userLoginParam) {
        User user = userMapper.getByAccount(userLoginParam.getAccount());

        if (user != null) {
            if (user.getPassword().equals(MD5Utils.getMd5Password(userLoginParam.getAccount(), userLoginParam.getPassword()))) {
                return doLogin(user);
            }
        }
        throw new FailedException(FailedInfo.FAILED_LOGIN.getErrorCode(), FailedInfo.FAILED_LOGIN.getErrorMsg());
    }

    @Override
    public Token getToken(String token) {
        if (token != null) {// 判断是否为空的token
            Token tokenMsg = redisUtils.get(Constant.LOGIN_KEY + ":" + token, Token.class);
            if (tokenMsg != null) {
                return tokenMsg;
            } else {
                tokenMsg = tokenMapper.getById(token);
                if (tokenMsg == null) {// 无效token
                    throw new FailedException(FailedInfo.ERROR_TOKEN.getErrorCode(), FailedInfo.ERROR_TOKEN.getErrorMsg());
                } else {
                    redisUtils.set(Constant.LOGIN_KEY + ":" + token, redisUtils.ObjectToString(tokenMsg), 1800000, TimeUnit.SECONDS);
                    return tokenMsg;
                }
            }
        }
        throw new FailedException(FailedInfo.EMPTY_TOKEN.getErrorCode(), FailedInfo.EMPTY_TOKEN.getErrorMsg());
    }

    /**
     * 执行登录操作
     * @param user 用户信息
     * @return 返回用户部分信息
     */
    private UserSO doLogin(User user) {
        Token token = tokenMapper.getByAccount(user.getAccount());

        String tokenId = UUID.randomUUID().toString().replace("-", "");
        if (token == null) {// 没有令牌新建令牌
            token = new Token();
            token.setId(tokenId);
            token.setAccount(user.getAccount());
            token.setCreatedTime(DateUtils.getTime());
            token.setUserName(user.getName());
            token.setUid(user.getId());
            if (tokenMapper.insert(token) == 0) {
                throw new FailedException(FailedInfo.ERROR_INSERT.getErrorCode(), FailedInfo.ERROR_INSERT.getErrorMsg());
            }
        } else {
            redisUtils.remove(Constant.LOGIN_KEY + ":" + token.getId());
            token.setId(tokenId);
            token.setCreatedTime(DateUtils.getTime());
            if (tokenMapper.update(token) == 0) {
                throw new FailedException(FailedInfo.ERROR_UPDATE.getErrorCode(), FailedInfo.ERROR_UPDATE.getErrorMsg());
            }
        }

        redisUtils.set(Constant.LOGIN_KEY + ":" + token.getId(), redisUtils.ObjectToString(token), 1800000, TimeUnit.MILLISECONDS);
        UserSO userSO = new UserSO(user);
        userSO.setToken(token.getId());
        return userSO;
    }
}
